package com.woniuxy.portal.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.common.consts.RedisConst;
import com.woniuxy.common.enums.UserStatus;
import com.woniuxy.common.enums.impl.BusinessCode;
import com.woniuxy.common.exception.Assert;
import com.woniuxy.portal.model.entity.User;
import com.woniuxy.portal.model.vo.LoginRequest;
import com.woniuxy.portal.model.vo.UserVo;
import com.woniuxy.portal.service.UserService;
import com.woniuxy.portal.mapper.UserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * @author HASEE
 * @description 针对表【t_user】的数据库操作Service实现
 * @createDate 2025-08-02 11:43:04
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    // 字段注入依赖（已优化）

    private final PasswordEncoder passwordEncoder;
    private final StringRedisTemplate stringRedisTemplate;

    // 构造器注入依赖（改为这个）
    @Autowired
    public UserServiceImpl(PasswordEncoder passwordEncoder, StringRedisTemplate stringRedisTemplate) {
        this.passwordEncoder = passwordEncoder;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 用户登录接口
     *
     * @param loginRequest 登录请求参数，包含账户、密码、验证码等信息
     * @return 登录成功返回用户信息，失败抛出相应业务异常
     */
    @Override
    public ResponseEntity<?> login(LoginRequest loginRequest) {
        // 从Redis中获取验证码
        String redisCode = stringRedisTemplate.opsForValue().get(loginRequest.getKey());
        // 检查验证码是否存在，如果 redisCode 为null则抛出"验证码已失效"异常
        Assert.error(redisCode, BusinessCode.INVALID_VERIFICATION);
        // 比较用户输入的验证码与Redis中存储的验证码是否一致，不一致则抛出"验证码错误"异常
        Assert.error(!redisCode.equalsIgnoreCase(loginRequest.getCode()), BusinessCode.VERIFICATION_ERROR);

        // 1、根据账户查询用户，校验用户：使用MyBatis-Plus查询用户，根据账户名精确匹配查找用户信息
        User user = this.getOne(Wrappers.lambdaQuery(User.class).eq(User::getAccount, loginRequest.getAccount()));
        // 检查用户是否存在，如果 user 为null则抛出"用户不存在"异常
        Assert.error(user, BusinessCode.USER_NOT_EXIST);
        // 2、校验密码：使用密码编码器比较用户输入密码与数据库存储密码是否匹配，不匹配则抛出"密码错误"异常
        Assert.error(!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword()), BusinessCode.PASSWORD_ERROR);

        // 登录成功后从Redis中删除已使用的验证码，防止重复使用
        stringRedisTemplate.delete(loginRequest.getKey());
        // 3、判断状态是否可用：检查用户状态是否为激活状态，如果不是则抛出"用户被冻结"异常
        Assert.error(!user.getState().equals(UserStatus.ACTIVE.getKey()), BusinessCode.USER_FROZEN_ERROR);

        // 所有验证通过后，返回包含用户信息的成功响应
        return ResponseEntity.ok(user);
    }

    /**
     * 根据用户ID查询用户信息
     * "keyGenerator" (自定义的缓存key生成策略)
     *
     * @param userId 用户ID
     * @return UserVo 用户信息VO对象
     */
    @Override
    @Cacheable(cacheNames = RedisConst.USER_DETAIL, keyGenerator = "keyGenerator")
    public UserVo findById(Long userId) {
        // 调用数据层查询
        User user = baseMapper.selectById(userId);
        // 复制属性
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);

        return userVo;
    }

}




